import { isNull, isUndefined, PagedList, PageParams, toString } from "mmb";
import { stringify, v4 as uuid } from "uuid"; // 临时生成订单,将来要切换成自定义生成规则
import {
  AfterSale,
  AfterSaleDetailItem,
  AfterSaleSlimDetailItem,
  ApplyAfterSaleParams,
  ApplyAfterSaleDetailItem,
  CancelAfterSaleParams,
  AuditAfterSaleParams,
  SendAfterSaleReturnGoodsParams,
  ReceiveAfterSaleReturnGoodsRarams,
  AfterSaleItemForC,
  AfterSaleItemForS,
  AfterSaleItemForB,
  AfterSaleItemForStore,
} from "./declareTypes";
import * as after_salepb from "../grpc-client/service/after_sale_pb";
import {
  getBgsAfterSaleOpSafely,
  getMetadata,
  getOptionsOfLight,
  wrapperGrpcError,
} from "../grpc-client/grpcAdapter";
import GrpcErrCode from "../grpc-client/grpcErrCode";
import { numberZeroValue, pbTimestampToJs, jsTimestampToPb } from "./helper";
import AfterSaleType from "../bg-enums/afterSaleType";
import GoodsReceivingStatus from "../bg-enums/goodsReceivingStatus";
import AfterSaleStatus from "../bg-enums/afterSaleStatus";
import AfterSaleCloseReason from "../bg-enums/afterSaleCloseReason";
import ActivityOwner from "../bg-enums/activityOwner";
import SearchTerm from "../bg-enums/searchTerm";

/****************************************************************************************/
/*                                   after_sale entity                                  */
/****************************************************************************************/

const afterSalePbToObject = (pb: after_salepb.AfterSaleEntity): AfterSale => {
  return {
    afterSaleId: toString(pb.getId()),
    applied: pbTimestampToJs(pb.getApplied())!,
    serialNumber: pb.getSerialNumber(),
    brandId: toString(pb.getBrandId()),
    activityId: toString(pb.getActivityId()),
    orderId: toString(pb.getOrderId()),
    orderSerialNumber: pb.getOrderSerialNumber(),
    userId: toString(pb.getUserId()),
    storeId: pb.getStoreId() === 0 ? undefined : toString(pb.getStoreId()),
    distributorId:
      pb.getDistributorId() === 0 ? undefined : toString(pb.getDistributorId()),
    distributorUserId:
      pb.getDistributorUserId() === 0
        ? undefined
        : toString(pb.getDistributorUserId()),
    spokesmanId: toString(pb.getSpokesmanId()),
    spokesmanUserId: toString(pb.getSpokesmanUserId()),
    type: pb.getType() as AfterSaleType,
    audited: pbTimestampToJs(pb.getAudited()),
    cancelled: pbTimestampToJs(pb.getCancelled()),
    sended: pbTimestampToJs(pb.getSended()),
    received: pbTimestampToJs(pb.getReceived()),
    refunded: pbTimestampToJs(pb.getRefunded()),
    afterSaleStatus: pb.getAfterSaleStatus() as AfterSaleStatus,
    amount: pb.getAmount(),
    isWholeRefund: pb.getIsWholeRefund(),
    afterSaleReason: pb.getAfterSaleReason(),
    closeReason:
      pb.getCloseReason() === ""
        ? undefined
        : (pb.getCloseReason() as AfterSaleCloseReason),
    remark: pb.getRemark(),
    refuseAfterSaleReason: pb.getRefuseAfterSaleReason(),
    returnGoodsAddressInfo:
      pb.getReturnGoodsAddressInfo() === ""
        ? undefined
        : JSON.parse(pb.getReturnGoodsAddressInfo()),
    returnGoodsLogisticsInfo:
      pb.getReturnGoodsLogisticsInfo() === ""
        ? undefined
        : JSON.parse(pb.getReturnGoodsLogisticsInfo()),

    details: pb.getAfterSaleDetailsList().map(afterSaleDetailItemPbToObject),
    brandName: pb.getBrandName(),
    brandPic: pb.getBrandPic(),
    brandTel: pb.getBrandTel(),
    storeName: pb.getStoreName() == "" ? undefined : pb.getStoreName(),
    storePic: pb.getStorePic() == "" ? undefined : pb.getStorePic(),
    storeTel: pb.getStoreTel() == "" ? undefined : pb.getStoreTel(),
    activityOwner: pb.getActivityOwner() as ActivityOwner,
    parentActivityOwner:
      pb.getParentActivityOwner() == ""
        ? undefined
        : (pb.getParentActivityOwner() as ActivityOwner),
    parentActivityName:
      pb.getParentActivityName() == "" ? undefined : pb.getParentActivityName(),
    parentActivityTel:
      pb.getParentActivityTel() == "" ? undefined : pb.getParentActivityTel(),
    activityName: pb.getActivityName(),
    activityTel: pb.getActivityTel(),
    buyerNickName: pb.getBuyerNickName(),
    buyerPic: pb.getBuyerPic(),
    buyerTel: pb.getBuyerTel(),
  };
};

const afterSaleDetailItemPbToObject = (
  pb: after_salepb.AfterSaleDetailItemEntity
): AfterSaleDetailItem => {
  return {
    afterSaleDetailId: toString(pb.getId()),
    productId: toString(pb.getProductId()),
    productName: pb.getProductName(),
    productSpecId: toString(pb.getProductSpecId()),
    productSpecKey: pb.getProductSpecKey(),
    productSpecName: pb.getProductSpecName(),
    productWithSpecName: pb.getProductWithSpecName(),
    storageKey: pb.getStorageKey(),
    productPics: pb.getProductPicsList(),
    quantity: pb.getQuantity(),
    price: pb.getPrice(),
    goodsReceivingStatus: pb.getGoodsReceivingStatus() as GoodsReceivingStatus,
  };
};

const applyAfterSaleDetailItemObjectToPb = (o: ApplyAfterSaleDetailItem) => {
  const pb = new after_salepb.ApplyAfterSaleRequest.ApplyAfterSaleDetailItem();
  pb.setOrderDetailId(Number(o.orderDetailId));
  pb.setQuantity(o.quantity);
  pb.setGoodsReceivingStatus(o.goodsReceivingStatus);
  return pb;
};

/****************************************************************************************/
/*                                   after_sale cmd                                     */
/****************************************************************************************/

export const applyAfterSale = async ({
  userId,
  orderSerialNumber,
  type,
  afterSaleReason,
  remark,
  details,
}: ApplyAfterSaleParams): Promise<AfterSale> => {
  const cl = getBgsAfterSaleOpSafely();
  const req = new after_salepb.ApplyAfterSaleRequest();
  req.setUserId(Number(userId));
  req.setOrderSerialNumber(orderSerialNumber);
  req.setType(type);
  req.setApplyAfterSaleDetailsList(
    details.map(applyAfterSaleDetailItemObjectToPb)
  );
  req.setAfterSaleReason(afterSaleReason);
  if (!isUndefined(remark)) {
    req.setRemark(remark);
  }

  return new Promise((resolve, reject) => {
    cl.applyAfterSale(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      const afterSale = afterSalePbToObject(res.getAfterSale()!);
      resolve(afterSale);
    });
  });
};

export const cancelAfterSale = async ({
  afterSaleSerialNumber,
  userId,
}: CancelAfterSaleParams): Promise<AfterSale> => {
  const cl = getBgsAfterSaleOpSafely();
  const req = new after_salepb.CancelAfterSaleRequest();
  req.setAfterSaleSerialNumber(afterSaleSerialNumber);
  req.setUserId(Number(userId));

  return new Promise((resolve, reject) => {
    cl.cancelAfterSale(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      const afterSale = afterSalePbToObject(res.getAfterSale()!);
      resolve(afterSale);
    });
  });
};

export const auditAfterSale = async ({
  afterSaleSerialNumber,
  brandId,
  isRefuse,
  refuseReason,
}: AuditAfterSaleParams): Promise<AfterSale> => {
  const cl = getBgsAfterSaleOpSafely();
  const req = new after_salepb.AuditAfterSaleRequest();
  req.setAfterSaleSerialNumber(afterSaleSerialNumber);
  req.setBrandId(Number(brandId));
  req.setIsRefuse(isRefuse);
  if (!isUndefined(refuseReason)) {
    req.setRefuseReason(refuseReason);
  }

  return new Promise((resolve, reject) => {
    cl.auditAfterSale(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      const afterSale = afterSalePbToObject(res.getAfterSale()!);
      resolve(afterSale);
    });
  });
};

export const sendAfterSaleReturnGoods = async ({
  afterSaleSerialNumber,
  userId,
  platformId,
  platformName,
  platformNo,
}: SendAfterSaleReturnGoodsParams): Promise<AfterSale> => {
  const cl = getBgsAfterSaleOpSafely();
  const req = new after_salepb.SendAfterSaleReturnGoodsRequest();
  req.setAfterSaleSerialNumber(afterSaleSerialNumber);
  req.setUserId(Number(userId));
  req.setPlatformId(Number(platformId));
  req.setPlatformName(platformName);
  req.setPlatformNo(platformNo);

  return new Promise((resolve, reject) => {
    cl.sendAfterSaleReturnGoods(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const afterSale = afterSalePbToObject(res.getAfterSale()!);
        resolve(afterSale);
      }
    );
  });
};

export const receiveAfterSaleReturnGoods = async ({
  afterSaleSerialNumber,
  brandId,
  agreeReceive,
  refuseAfterSaleReason,
}: ReceiveAfterSaleReturnGoodsRarams): Promise<AfterSale> => {
  const cl = getBgsAfterSaleOpSafely();
  const req = new after_salepb.ReceiveAfterSaleReturnGoodsRequest();
  req.setAfterSaleSerialNumber(afterSaleSerialNumber);
  req.setBrandId(Number(brandId));
  req.setAgreeReceive(agreeReceive);
  if (!isUndefined(refuseAfterSaleReason)) {
    req.setRefuseAfterSaleReason(refuseAfterSaleReason);
  }

  return new Promise((resolve, reject) => {
    cl.receiveAfterSaleReturnGoods(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const afterSale = afterSalePbToObject(res.getAfterSale()!);
        resolve(afterSale);
      }
    );
  });
};

/****************************************************************************************/
/*                                   after_sale query                                   */
/****************************************************************************************/

export const getAfterSaleBySerialNumber = async (
  serialNumber: string
): Promise<AfterSale | undefined> => {
  const cl = getBgsAfterSaleOpSafely();
  const req = new after_salepb.GetAfterSaleRequest();
  req.setSerialNumber(serialNumber);
  return new Promise((resolve, reject) => {
    cl.getAfterSale(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        if (opRet.getCode() === GrpcErrCode.NOT_FOUND) {
          resolve(undefined);
          return;
        } else {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
      }
      resolve(afterSalePbToObject(res.getAfterSale()!));
    });
  });
};

export const getAfterSale = async (
  afterSaleId: string
): Promise<AfterSale | undefined> => {
  const cl = getBgsAfterSaleOpSafely();
  const req = new after_salepb.GetAfterSaleRequest();
  req.setAfterSaleId(Number(afterSaleId));
  return new Promise((resolve, reject) => {
    cl.getAfterSale(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        if (opRet.getCode() === GrpcErrCode.NOT_FOUND) {
          resolve(undefined);
          return;
        } else {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
      }
      resolve(afterSalePbToObject(res.getAfterSale()!));
    });
  });
};

/****************************************************************************************/
/*                                   after_sale joins entity                            */
/****************************************************************************************/

const afterSaleSlimDetailItemPbToObject = (
  pb: after_salepb.AfterSaleSlimDetailItemEntity
): AfterSaleSlimDetailItem => {
  return {
    productId: toString(pb.getProductId()),
    productName: pb.getProductName(),
    productSpecId: toString(pb.getProductSpecId()),
    productSpecKey: pb.getProductSpecKey(),
    productSpecName: pb.getProductSpecName(),
    productWithSpecName: pb.getProductWithSpecName(),
    storageKey: pb.getStorageKey(),
    productPics: pb.getProductPicsList(),
    quantity: pb.getQuantity(),
    price: pb.getPrice(),
  };
};

const afterSaleItemForCPbToObject = (
  pb: after_salepb.AfterSaleItemForCEntity
): AfterSaleItemForC => {
  return {
    afterSaleId: toString(pb.getId()),
    applied: pbTimestampToJs(pb.getApplied())!,
    serialNumber: pb.getSerialNumber(),
    brandId: toString(pb.getBrandId()),
    activityId: toString(pb.getActivityId()),
    afterSaleStatus: pb.getAfterSaleStatus() as AfterSaleStatus,
    amount: pb.getAmount(),
    type: pb.getType() as AfterSaleType,
    closeReason:
      pb.getCloseReason() === ""
        ? undefined
        : (pb.getCloseReason() as AfterSaleCloseReason),
    details: pb
      .getAfterSaleSlimDetailsList()
      .map(afterSaleSlimDetailItemPbToObject),
    brandName: pb.getBrandName(),
    brandPic: pb.getBrandPic(),
    brandTel: pb.getBrandTel(),
    activityName: pb.getActivityName(),
    activityTel: pb.getActivityTel(),
  };
};

const afterSaleItemForSPbToObject = (
  pb: after_salepb.AfterSaleItemForSEntity
): AfterSaleItemForS => {
  return {
    afterSaleId: toString(pb.getId()),
    applied: pbTimestampToJs(pb.getApplied())!,
    serialNumber: pb.getSerialNumber(),
    brandId: toString(pb.getBrandId()),
    activityId: toString(pb.getActivityId()),
    spokesmanId: toString(pb.getSpokesmanId()),
    spokesmanUserId: toString(pb.getSpokesmanUserId()),
    afterSaleStatus: pb.getAfterSaleStatus() as AfterSaleStatus,
    amount: pb.getAmount(),
    type: pb.getType() as AfterSaleType,
    closeReason:
      pb.getCloseReason() === ""
        ? undefined
        : (pb.getCloseReason() as AfterSaleCloseReason),
    details: pb
      .getAfterSaleSlimDetailsList()
      .map(afterSaleSlimDetailItemPbToObject),
    brandName: pb.getBrandName(),
    brandPic: pb.getBrandPic(),
    brandTel: pb.getBrandTel(),
    activityName: pb.getActivityName(),
    activityTel: pb.getActivityTel(),
    buyerNickName: pb.getBuyerNickName(),
    buyerPic: pb.getBuyerPic(),
  };
};

const afterSaleItemForBPbToObject = (
  pb: after_salepb.AfterSaleItemForBEntity
): AfterSaleItemForB => {
  return {
    afterSaleId: toString(pb.getId()),
    applied: pbTimestampToJs(pb.getApplied())!,
    serialNumber: pb.getSerialNumber(),
    brandId: toString(pb.getBrandId()),
    activityId: toString(pb.getActivityId()),
    afterSaleStatus: pb.getAfterSaleStatus() as AfterSaleStatus,
    amount: pb.getAmount(),
    type: pb.getType() as AfterSaleType,
    closeReason:
      pb.getCloseReason() === ""
        ? undefined
        : (pb.getCloseReason() as AfterSaleCloseReason),
    details: pb
      .getAfterSaleSlimDetailsList()
      .map(afterSaleSlimDetailItemPbToObject),
    brandName: pb.getBrandName(),
    brandPic: pb.getBrandPic(),
    brandTel: pb.getBrandTel(),
    activityName: pb.getActivityName(),
    activityTel: pb.getActivityTel(),
    buyerNickName: pb.getBuyerNickName(),
    buyerPic: pb.getBuyerPic(),
  };
};

const afterSaleItemForStorePbToObject = (
  pb: after_salepb.AfterSaleItemForStoreEntity
): AfterSaleItemForStore => {
  return {
    afterSaleId: toString(pb.getId()),
    applied: pbTimestampToJs(pb.getApplied())!,
    serialNumber: pb.getSerialNumber(),
    brandId: toString(pb.getBrandId()),
    storeId: toString(pb.getStoreId()),
    distributorId: toString(pb.getDistributorId()),
    distributorUserId: toString(pb.getDistributorUserId()),
    activityId: toString(pb.getActivityId()),
    afterSaleStatus: pb.getAfterSaleStatus() as AfterSaleStatus,
    amount: pb.getAmount(),
    type: pb.getType() as AfterSaleType,
    closeReason:
      pb.getCloseReason() === ""
        ? undefined
        : (pb.getCloseReason() as AfterSaleCloseReason),
    details: pb
      .getAfterSaleSlimDetailsList()
      .map(afterSaleSlimDetailItemPbToObject),
    brandName: pb.getBrandName(),
    brandPic: pb.getBrandPic(),
    brandTel: pb.getBrandTel(),
    storeName: pb.getStoreName(),
    storePic: pb.getStorePic(),
    storeTel: pb.getStoreTel(),
    activityName: pb.getActivityName(),
    activityTel: pb.getActivityTel(),
    buyerNickName: pb.getBuyerNickName(),
    buyerPic: pb.getBuyerPic(),
  };
};

export const listAfterSaleItemsForC = async (
  userId: string,
  pager: PageParams
): Promise<PagedList<AfterSaleItemForC>> => {
  const cl = getBgsAfterSaleOpSafely();
  const req = new after_salepb.ListAfterSaleItemsForCRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setTs(jsTimestampToPb(pager.ts));
  req.setUserId(Number(userId));

  return new Promise((resolve, reject) => {
    cl.listAfterSaleItemsForC(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const ret: PagedList<AfterSaleItemForC> = {
          total: 0,
          items: [],
        };
        ret.total = res.getTotal();
        ret.items = res
          .getAfterSaleItemsForCList()
          .map(afterSaleItemForCPbToObject);
        resolve(ret);
      }
    );
  });
};

export interface ListAfterSaleItemsForSParam {
  userId: string;
  searchTerm?: SearchTerm;
  searchValue?: string;
}

export const listAfterSaleItemsForS = async (
  { userId, searchTerm, searchValue }: ListAfterSaleItemsForSParam,
  pager: PageParams
): Promise<PagedList<AfterSaleItemForS>> => {
  const cl = getBgsAfterSaleOpSafely();
  const req = new after_salepb.ListAfterSaleItemsForSRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setTs(jsTimestampToPb(pager.ts));
  req.setUserId(Number(userId));
  if (!isUndefined(searchTerm)) {
    req.setSearchTerm(searchTerm);
  }
  if (!isUndefined(searchValue)) {
    req.setSearchValue(searchValue);
  }

  return new Promise((resolve, reject) => {
    cl.listAfterSaleItemsForS(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const ret: PagedList<AfterSaleItemForS> = {
          total: 0,
          items: [],
        };
        ret.total = res.getTotal();
        ret.items = res
          .getAfterSaleItemsForSList()
          .map(afterSaleItemForSPbToObject);
        resolve(ret);
      }
    );
  });
};

export interface ListAfterSaleItemsForBParam {
  brandId: string;
  searchTerm?: SearchTerm;
  searchValue?: string;
}

export const listAfterSaleItemsForB = async (
  { brandId, searchTerm, searchValue }: ListAfterSaleItemsForBParam,
  pager: PageParams
): Promise<PagedList<AfterSaleItemForB>> => {
  const cl = getBgsAfterSaleOpSafely();
  const req = new after_salepb.ListAfterSaleItemsForBRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setTs(jsTimestampToPb(pager.ts));
  req.setBrandId(Number(brandId));
  if (!isUndefined(searchTerm)) {
    req.setSearchTerm(searchTerm);
  }
  if (!isUndefined(searchValue)) {
    req.setSearchValue(searchValue);
  }

  return new Promise((resolve, reject) => {
    cl.listAfterSaleItemsForB(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const ret: PagedList<AfterSaleItemForB> = {
          total: 0,
          items: [],
        };
        ret.total = res.getTotal();
        ret.items = res
          .getAfterSaleItemsForBList()
          .map(afterSaleItemForBPbToObject);
        resolve(ret);
      }
    );
  });
};

export interface ListAfterSaleItemsForStoreParam {
  storeId: string;
  searchTerm?: SearchTerm;
  searchValue?: string;
}

export const listAfterSaleItemsForStore = async (
  { storeId, searchTerm, searchValue }: ListAfterSaleItemsForStoreParam,
  pager: PageParams
): Promise<PagedList<AfterSaleItemForB>> => {
  const cl = getBgsAfterSaleOpSafely();
  const req = new after_salepb.ListAfterSaleItemsForStoreRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setTs(jsTimestampToPb(pager.ts));
  req.setStoreId(Number(storeId));
  if (!isUndefined(searchTerm)) {
    req.setSearchTerm(searchTerm);
  }
  if (!isUndefined(searchValue)) {
    req.setSearchValue(searchValue);
  }

  return new Promise((resolve, reject) => {
    cl.listAfterSaleItemsForStore(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const ret: PagedList<AfterSaleItemForB> = {
          total: 0,
          items: [],
        };
        ret.total = res.getTotal();
        ret.items = res
          .getAfterSaleItemsForStoreList()
          .map(afterSaleItemForStorePbToObject);
        resolve(ret);
      }
    );
  });
};